package main

import (
	"encoding/json"
	"fmt"
	"github.com/schollz/progressbar/v3"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

/*
	这个文件中都是对于文件进行具体修改的处理
*/

func isJson(filePath string) bool {
	suffixSli := strings.Split(filePath, ".")
	suffix := suffixSli[len(suffixSli)-1]
	return suffix == "json"
}

func loadJson(jsonPath string) (map[string][]string, error) {
	jsonFile, err := ioutil.ReadFile(jsonPath)
	if err != nil {
		return nil, fmt.Errorf("file reading failure: %v", err)
	}

	var apiMap map[string][]string
	err = json.Unmarshal(jsonFile, &apiMap)
	if err != nil {
		return nil, fmt.Errorf("parsing file failed: %v", err)
	}

	return apiMap, nil
}

// 判断文件是否存在
func fileExists(fileName string) bool {
	_, err := os.Stat(fileName)
	return !os.IsNotExist(err)
}

// 删除文件的函数
func deleteFile(fileName string) error {
	err := os.Remove(fileName)
	if err != nil {
		return fmt.Errorf("failed to delete: %v", err)
	}
	return nil
}

// 模糊查询
func fuzzySearch(query string, apiMap map[string][]string) map[string][]string {
	results := make(map[string][]string)
	for key, value := range apiMap {
		if strings.Contains(key, query) {
			//fmt.Println(key, "\t", query)
			results[key] = value
		}
	}
	return results
}

func saveToJson(tag string, apiList []string, filename string) error {
	// 尝试读取现有文件
	existingData := make(map[string][]string)
	if _, err := os.Stat(filename); err == nil {
		// 文件存在，读取内容
		fileContent, err := ioutil.ReadFile(filename)
		if err != nil {
			log.Fatalf(Red+"failed to read existing JSON file: %v"+Reset, err)
		}
		// 读取文件解析到map中
		err = json.Unmarshal(fileContent, &existingData)
		if err != nil {
			log.Fatalf(Red+"failed to unmarshal existing JSON data: %v"+Reset, err)
		}
	}

	// 更新或添加新的键值对
	for _, api := range apiList {
		if !contains(existingData[tag], api) {
			existingData[tag] = append(existingData[tag], api)
		}
	}
	jsonData, err := json.MarshalIndent(existingData, "", "  ")
	if err != nil {
		log.Fatalf(Red+"failed to marshal data to JSON: %v"+Reset, err)
	}
	err = ioutil.WriteFile(filename, jsonData, 0644)
	if err != nil {
		log.Fatalf(Red+"failed to write JSON to file: %v"+Reset, err)
	}

	return nil
}

// 检查切片中是否包含特定值
func contains(slice []string, item string) bool {
	for _, a := range slice {
		if a == item {
			return true
		}
	}
	return false
}

// 处理tag插入

// ApiTags  Temporary_api.json 对应的结构
type ApiTags map[string][]string

func getTmpInfo() map[string]string {
	// 打开文件
	file, err := os.Open("./Temporary_api.json")
	if err != nil {
		log.Fatalf(Red+"Failed to open file: %v"+Reset, err)
	}
	defer file.Close()
	var apiTags ApiTags
	decoder := json.NewDecoder(file)
	err = decoder.Decode(&apiTags)
	if err != nil {
		log.Fatalf("Failed to decode JSON: %v", err)
	}

	MiddleMap := make(map[string]string)

	// 提取 API 路径和标签放到内存中
	for tag, apis := range apiTags {
		for _, api := range apis {
			// 将 API 路径和标签存入 map
			MiddleMap[api] = tag
		}
	}
	// 测试
	//for apiPath, tag := range MiddleMap {
	//	fmt.Printf("API Path: %s, Tag: %s\n", apiPath, tag)
	//}
	return MiddleMap
}

// OpenAPIS 结构体用于解析和修改 OpenAPI JSON
type OpenAPIS struct {
	OpenAPI    string                                       `json:"openapi"`
	Info       struct{ Title, Version string }              `json:"info"`
	Paths      map[string]map[string]map[string]interface{} `json:"paths"`
	Components struct {
		Schemas map[string]interface{} `json:"schemas"`
	} `json:"components"`
}

// 写入openapi.json
func fillJson(midMap map[string]string, openapiFP string) {

	// 读取 OpenAPI JSON 文件
	file, err := os.Open(openapiFP)
	if err != nil {
		fmt.Printf(Red+"Failed to open OpenAPI file: %v\n"+Reset, err)
		return
	}
	defer file.Close()

	// 解析 OpenAPI JSON
	data, err := ioutil.ReadAll(file)
	if err != nil {
		fmt.Printf(Red+"Failed to read OpenAPI file: %v\n"+Reset, err)
		return
	}

	var openapis OpenAPIS
	if err = json.Unmarshal(data, &openapis); err != nil {
		fmt.Printf(Red+"Failed to unmarshal OpenAPI JSON: %v\n"+Reset, err)
		return
	}
	bar := progressbar.New(len(midMap))

	for key, val := range midMap {
		keySli := strings.Split(key, "█")
		apiPath := keySli[0]
		method := keySli[1]

		if methodDetails, ok := openapis.Paths[apiPath][method]; ok {
			// 添加标签
			if tags, ok := methodDetails["tags"].([]interface{}); ok {
				// 将新标签添加到现有标签中
				tagExists := false
				for _, tag := range tags {
					if t, ok := tag.(string); ok && t == val {
						tagExists = true
						break
					}
				}
				if !tagExists {
					tags = append(tags, val)
				}
				methodDetails["tags"] = tags
			} else {
				methodDetails["tags"] = []interface{}{val}
			}
		}
		//fmt.Printf("%s, %s, %s\n", apiPath, method, tag)

		// 写回
		output, err := json.MarshalIndent(openapis, "", "  ")
		if err != nil {
			fmt.Printf(Red+"Failed to marshal updated OpenAPI JSON: %v\n"+Reset, err)
			return
		}

		err = ioutil.WriteFile(openapiFP, output, 0644)
		if err != nil {
			fmt.Printf(Red+"Failed to write updated OpenAPI file: %v\n"+Reset, err)
			return
		}
		bar.Add(1)
	}
	fmt.Println(Green + "\nOpenAPI JSON updated successfully." + Reset)
	fp := getFP()
	LoadFile(fp)
	if fileExists("Temporary_api.json") {
		err := deleteFile("Temporary_api.json")
		if err != nil {
			return
		}
	} else {
		log.Fatalf(Red + "File not found" + Reset)
	}
}

func delJson(midMap map[string]string, openapiFP string) {
	// 读取 OpenAPI JSON 文件
	file, err := os.Open(openapiFP)
	if err != nil {
		fmt.Printf(Red+"Failed to open OpenAPI file: %v\n"+Reset, err)
		return
	}
	defer file.Close()

	// 解析 OpenAPI JSON
	data, err := ioutil.ReadAll(file)
	if err != nil {
		fmt.Printf(Red+"Failed to read OpenAPI file: %v\n"+Reset, err)
		return
	}

	var openapis OpenAPIS
	if err = json.Unmarshal(data, &openapis); err != nil {
		fmt.Printf(Red+"Failed to unmarshal OpenAPI JSON: %v\n"+Reset, err)
		return
	}
	bar := progressbar.New(len(midMap))

	for key, val := range midMap {
		keySli := strings.Split(key, "█")
		apiPath := keySli[0]
		method := keySli[1]

		if methodDetails, ok := openapis.Paths[apiPath][method]; ok {
			if tags, ok := methodDetails["tags"].([]interface{}); ok {
				// 检查标签是否存在并删除
				for i, tag := range tags {
					if t, ok := tag.(string); ok && t == val {
						// 从 tags 中删除标签
						tags = append(tags[:i], tags[i+1:]...)
						break
					}
				}
				methodDetails["tags"] = tags
			}
		}
		//fmt.Printf("%s, %s, %s\n", apiPath, method, tag)

		// 写回
		output, err := json.MarshalIndent(openapis, "", "  ")
		if err != nil {
			fmt.Printf(Red+"Failed to marshal updated OpenAPI JSON: %v\n"+Reset, err)
			return
		}

		err = ioutil.WriteFile(openapiFP, output, 0644)
		if err != nil {
			fmt.Printf(Red+"Failed to write updated OpenAPI file: %v\n"+Reset, err)
			return
		}
		bar.Add(1)
	}
	fmt.Println(Green + "\nOpenAPI JSON updated successfully." + Reset)
	fp := getFP()
	LoadFile(fp)
	if fileExists("Temporary_api.json") {
		err := deleteFile("Temporary_api.json")
		if err != nil {
			return
		}
	} else {
		log.Fatalf(Red + "File not found" + Reset)
	}
}
